Skip to contentMethod: {...}
1: /*
2: * Copyright (c) 1997, 2021 Oracle and/or its affiliates and others.
3: * All rights reserved.
4: * Copyright 2004 The Apache Software Foundation
5: *
6: * Licensed under the Apache License, Version 2.0 (the "License");
7: * you may not use this file except in compliance with the License.
8: * You may obtain a copy of the License at
9: *
10: * http://www.apache.org/licenses/LICENSE-2.0
11: *
12: * Unless required by applicable law or agreed to in writing, software
13: * distributed under the License is distributed on an "AS IS" BASIS,
14: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15: * See the License for the specific language governing permissions and
16: * limitations under the License.
17: */
18:
19: package jakarta.el;
20:
21: import static java.io.File.separator;
22:
23: import java.io.File;
24: import java.io.FileInputStream;
25: import java.lang.reflect.Constructor;
26: import java.security.AccessController;
27: import java.security.PrivilegedAction;
28: import java.util.Iterator;
29: import java.util.Properties;
30: import java.util.ServiceLoader;
31:
32: class FactoryFinder {
33:
34: private static final boolean IS_SECURITY_ENABLED = (System.getSecurityManager() != null);
35:
36: /**
37: * Creates an instance of the specified class using the specified <code>ClassLoader</code> object.
38: *
39: * @exception ELException if the given class could not be found or could not be instantiated
40: */
41: private static Object newInstance(String className, ClassLoader classLoader, Properties properties) {
42: try {
43: Class<?> spiClass;
44: if (classLoader == null) {
45: spiClass = Class.forName(className);
46: } else {
47: spiClass = classLoader.loadClass(className);
48: }
49:
50: if (properties != null) {
51: Constructor<?> constr = null;
52: try {
53: constr = spiClass.getConstructor(Properties.class);
54: } catch (Exception ex) {
55: }
56:
57: if (constr != null) {
58: return constr.newInstance(properties);
59: }
60: }
61:
62: if (IS_SECURITY_ENABLED) {
63: return AccessController.doPrivileged(new PrivilegedAction < Object > () {@Override
64: public Object run() {
65: try {
66: return spiClass.getDeclaredConstructor().newInstance();
67: } catch(Exception x) {
68: throw new ELException("Provider " + className + " could not be instantiated: " + x, x);
69: }
70: }
71: });
72: } else {
73: return spiClass.getDeclaredConstructor().newInstance();
74: }
75:
76: } catch (ClassNotFoundException x) {
77: throw new ELException("Provider " + className + " not found", x);
78: } catch (Exception x) {
79: throw new ELException("Provider " + className + " could not be instantiated: " + x, x);
80: }
81: }
82:
83: /**
84: * Finds the implementation <code>Class</code> object for the given factory. The following search order is used:
85: * <ol>
86: * <li>{@link ServiceLoader} lookup using <code>serviceClass</code></li>
87: * <li>Property file located as <code>$java.home/lib/el.properties</code></li>
88: * <li>System property lookup using <code>factoryId</code></li>
89: * <li>Create an instance of <code>fallbackClassName</code></li>
90: * </ol>
91: * This method is package private so that this code can be shared.
92: *
93: * @return the <code>Class</code> object of the specified message factory; may not be <code>null</code>
94: *
95: * @param serviceClass The class to use when searching for the factory using the ServiceLoader mechanism
96: * @param factoryId the name of the factory to find, which is a system property
97: * @param fallbackClassName the implementation class name, which is to be used only if nothing else is found;
98: * <code>null</code> to indicate that there is no fallback class name
99: * @exception ELException if there is an error
100: */
101: static Object find(Class<?> serviceClass, String factoryId, String fallbackClassName, Properties properties) {
102: ClassLoader classLoader;
103: try {
104: if (IS_SECURITY_ENABLED) {
105: classLoader = AccessController.doPrivileged(new PrivilegedAction < ClassLoader > () {@Override
106: public ClassLoader run() {
107: return Thread.currentThread().getContextClassLoader();
108: }
109: });
110: } else {
111: classLoader = Thread.currentThread().getContextClassLoader();
112: }
113: } catch (Exception x) {
114: throw new ELException(x.toString(), x);
115: }
116:
117: // try to find services in CLASSPATH
118: try {
119: ServiceLoader<?> serviceLoader = ServiceLoader.load(serviceClass, classLoader);
120: Iterator<?> iter = serviceLoader.iterator();
121: while (iter.hasNext()) {
122: Object service = iter.next();
123: if (service != null) {
124: return service;
125: }
126: }
127: } catch (Exception ex) {
128: }
129:
130: // Try to read from $java.home/lib/el.properties
131: try {
132: String factoryClassName = null;
133: if (IS_SECURITY_ENABLED) {
134: factoryClassName = AccessController.doPrivileged(
135: new PrivilegedAction < String > () {@Override
136: public String run() {
137: return getFactoryClassName(factoryId);
138: }
139: });
140:
141: } else {
142: factoryClassName = getFactoryClassName(factoryId);
143: }
144: if (factoryClassName != null) {
145: return newInstance(factoryClassName, classLoader, properties);
146: }
147: } catch (Exception ex) {
148: }
149:
150: // Use the system property
151: try {
152: String systemProp;
153: if (IS_SECURITY_ENABLED) {
154: systemProp = AccessController.doPrivileged(
155: new PrivilegedAction < String > () {@Override
156: public String run() {
157: return System.getProperty(factoryId);
158: }
159: });
160: } else {
161: systemProp = System.getProperty(factoryId);
162: }
163: if (systemProp != null) {
164: return newInstance(systemProp, classLoader, properties);
165: }
166: } catch (SecurityException se) {
167: }
168:
169: if (fallbackClassName == null) {
170: throw new ELException("Provider for " + factoryId + " cannot be found", null);
171: }
172:
173: return newInstance(fallbackClassName, classLoader, properties);
174: }
175:
176: private static String getFactoryClassName(String factoryId) {
177: String factoryClass = null;
178: String javah = System.getProperty("java.home");
179: String configFileName = javah + separator + "lib" + separator + "el.properties";
180:
181: File configFile = new File(configFileName);
182: if (configFile.exists()) {
183: Properties props = new Properties();
184: try {
185: props.load(new FileInputStream(configFile));
186: } catch(Exception e) {}
187: factoryClass = props.getProperty(factoryId);
188: }
189: return factoryClass;
190: }
191: }